#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @Time      :2021/7/15 15:51
# @Author    :cjw
"""jwt生成令牌"""
from datetime import datetime, timedelta
from copy import deepcopy
from typing import Optional

from jose import jwt, JWTError

from app.core.config import settings
from app.utils.log import logger


def create_access_token(data: dict, expires_delta: Optional[timedelta] = None) -> str:
    """
    生成访问令牌
    :param data: 令牌携带的数据
    :param expires_delta: 令牌过期时间
    :return:
    """
    to_encode = deepcopy(data)

    # 令牌过期时间，默认15分钟
    if expires_delta:
        expire = datetime.utcnow() + expires_delta
    else:
        expire = datetime.utcnow() + timedelta(minutes=15)

    # 更新令牌携带的数据，然后生成令牌并返回
    to_encode.update({'exp': expire, 'sub': settings.ACCESS_TOKEN_JWT_SUBJECT})
    encode_jwt = jwt.encode(to_encode, settings.SECRET_KEY, algorithm=settings.ALGORITHM)
    return encode_jwt


def generate_password_reset_token(email: str) -> str:
    """
    生成密码重置令牌
    :param email: 重置密码用户邮箱
    :return:
    """
    # 令牌有效期时间处理
    delta = timedelta(hours=settings.EMAIL_RESET_TOKEN_EXPIRE_HOURS)
    now = datetime.utcnow()
    expires = now + delta
    exp = expires.timestamp()  # 转化为时间戳

    # 生成令牌并返回
    encoded_jwt = jwt.encode(
        {'exp': exp, 'nbf': now, 'sub': settings.PASSWORD_RESET_JWT_SUBJECT, 'email': email},
        settings.SECRET_KEY,
        algorithm=settings.ALGORITHM
    )
    return encoded_jwt


def verify_password_reset_token(token: str) -> Optional[str]:
    """
    密码重置token验证
    :param token:令牌
    :return: 返回重置密码的用户邮箱
    """
    try:
        decoded_token = jwt.decode(token, settings.SECRET_KEY, algorithms=settings.ALGORITHM)
        assert decoded_token.get('sub') == settings.PASSWORD_RESET_JWT_SUBJECT
        return decoded_token.get('email')
    except JWTError as e:
        logger.error(f'密码重置token验证失败：{e}')
        return None
